#include "EController.h"
#include "DefineCommon.h"
#include "EItem.h"
#include "EItemMetaProperty.h"
#include "EVariant.h"
#include <cstddef>
#include <EItemManager.h>
#include <ECommandManager.h>
//#include <asm-generic/errno.h>
//#include <cstddef>
//#include <iterator>


EController::EController()
{
    m_rootEItem = NewSmartPtr(EItem)();
}

EController::~EController()
{
}
    
long EController::getTag()
{
    return (long)this;
}

void EController::setRootItem(EItemPtr item)
{
    this->m_rootEItem = item;
}

EItemPtr EController::getRootItem()
{
    return this->m_rootEItem;
}

void EController::refresh()
{
    this->travelEItem(this->m_rootEItem);

    ECommandPtr newCmd = NewSmartPtr(ECommand)();
    newCmd->setSender( this->getTag() );
    newCmd->setSenderName(this->getName());
    newCmd->setName("c:refreshItem");
    newCmd->setIfEnableUndo(false);
    ECommandManager::instance()->pushECommand(newCmd);
}

bool EController::handleEItem(EItemPtr item, int depth, EItemPtr parentItem)
{
    return true;
}

EItemPtr EController::getSelectedItem()
{
    EItemPtr item = this->m_selectedEItem;
    if(item == nullptr)
    {
        item = this->getRootItem();
    }
    return item;
}

EItemPtr EController::addItem(EItemPtr typeItem)
{
    EItemPtr newItem;
    EItemPtr parent = this->getSelectedItem();
    if(parent == nullptr)
    {
        ELOG_ERROR("parent==nullptr");
        return newItem;
    }

    newItem = EItemManager::instance()->newItem(typeItem);
    if(newItem == nullptr)
    {
        ELOG_ERROR("newItem==nullptr");
        return newItem;
    }

    bool ifAdded = parent->addChild(newItem);
    if(ifAdded)
    {
        //push the additem command
        ECommandPtr newCmd = NewSmartPtr(ECommand)();
        newCmd->setSender( (intptr_t)this );
        newCmd->setSenderName(this->getName());
        newCmd->setName("c:addItem");
        
        newCmd->getOrCreatMeta()->addProperty("tagItem", EVariant(newItem->getTag()));
        ECommandManager::instance()->pushECommand(newCmd);
    }

    return newItem;
}

bool EController::deleteItem(EItemPtr item)
{
    if(item == nullptr)
    {
        return false;
    }

    bool result = false;
    for(int i = 0 ; i < item->getParentCount(); i++)
    {
        result = item->getParent(i)->removeChild(item);
    }

    if(result)
    {
        //push the additem command
        ECommandPtr newCmd = NewSmartPtr(ECommand)();
        newCmd->setSender( (intptr_t)this );
        newCmd->setSenderName(this->getName());
        newCmd->setName("c:deleteItem");
        newCmd->setIfEnableUndo(false);
        newCmd->getOrCreatMeta()->addProperty("tagItem", EVariant(item->getTag()));
        ECommandManager::instance()->pushECommand(newCmd);
    }

    return result;
}

EItemPtr EController::copyItem(EItemPtr item)
{
    EItemPtr newItemPtr;
    if(item->getParentCount() == 0)
    {
        return newItemPtr;
    }

    if(item == nullptr)
    {
        ELOG_ERROR("Failed to copyItem, item==nullptr");
        return newItemPtr;
    }

    EString className = item->getOrCreatMeta()->getClassName();
    newItemPtr = EItemManager::instance()->newItem(className);

    item->getParent(item->getParentCount()-1)->addChild(newItemPtr);

    ECommandPtr newCmd = NewSmartPtr(ECommand)();
    newCmd->setSender( (intptr_t)this );
    newCmd->setSenderName(this->getName());
    newCmd->setName("c:copyItem");
    newCmd->getOrCreatMeta()->addProperty("tagItem", EVariant(newItemPtr->getTag()));
    ECommandManager::instance()->pushECommand(newCmd);

    //TODO: only new a EItem with same type, but the property is not synchronized
        
    return newItemPtr;
}

void EController::selectItem(EItemPtr item)
{
    this->m_selectedEItem = item;

    ECommandPtr newCmd = NewSmartPtr(ECommand)();
    newCmd->setSender( this->getTag() );
    newCmd->setSenderName(this->getName());
    newCmd->setName("c:selectItem");
    newCmd->setItemAdditional(item);
    newCmd->setIfEnableUndo(false);
    ECommandManager::instance()->pushECommand(newCmd);
}

void EController::disselectItem(EItemPtr item)
{
    ECommandPtr newCmd = NewSmartPtr(ECommand)();
    newCmd->setSender( this->getTag() );
    newCmd->setSenderName(this->getName());
    newCmd->setName("c:disselectItem");
    newCmd->setItemAdditional(item);
    newCmd->setIfEnableUndo(false);
    ECommandManager::instance()->pushECommand(newCmd);
}

void EController::handleCommand(const ECommandPtr& command)
{
}

void EController::addCmdSenderList(long p)
{
    this->m_cmdSenderList.push_back(p);
}

bool EController::ifCmdSenderValid(long p)
{
    bool result=false;
    for(size_t i = 0; i < this->m_cmdSenderList.size(); i++)
    {
        if (p == this->m_cmdSenderList[i]) 
        {
        result=true;
        break;
        }
    }
    return result;
}
